package com.atguigu.gull.gmall.gateway.filter;

import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;


/**
 * 如果过滤器命名规范，XXXGatewayFilterFactory，那么 XXX 就是当前过滤器的名称
 * 当前过滤器名称：Test2
 *
 * 如果不想用上述名称，也可以在本类下面重写name方法，进行修改。
 *
 * 如果有服务想要用该过滤器，直接在本服务(gateway-service)的配置文件中配置
 * filters:
 *      -Test2=/toLogin.html,/login
 * 要接收application.yml中传过来的 /toLogin.html,/login 参数，需要以下几个步骤，这几个步骤一般是固定的，基本不变
 * 1.创建Config内部类，
 * 2.将Config内部类泛型设置到本类
 * 3.为本类创建空参构造方法，在方法中传入Config内部类
 * 4.在本类中实现shortcutType方法，该方法用来解析 /toLogin.html,/login 是什么的参数类型，是字符串？是集合？是数组？还是其他的？
 * 5.确定 /toLogin.html,/login 的参数类型后，转换成我们想要的参数类型,以某种方式，使得Config内部类的paths属性被赋值
 * 6.实现apply后需要实现的方法,该方法可读取Config内部类
 */
//@Configuration 该类就是用来测试的，测试完成，注掉
public class Test2GatewayFilterFactory extends AbstractGatewayFilterFactory<Test2GatewayFilterFactory.Config> {//2.这里的泛型里面的类型，是本类的 内部类

    /**
     * 3.为本类创建空参构造方法，在方法中传入Config内部类
     */
    public Test2GatewayFilterFactory() {
        super(Config.class);
    }

    /**
     * 6.继承AbstractGatewayFilterFactory后必要实现的apply方法,
     * 该方法可读取Config内部类
     */
    @Override
    public GatewayFilter apply(Config config) {//这里的参数类型必须和本类上的泛型一致
        return new GatewayFilter() { //返回一个过滤器对象
            //过滤请求的方法
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("局部过滤器过滤了请求....");
                System.out.println(config.getPaths());
                //放行
                return chain.filter(exchange);
            }
        };
    }

    /*@Override
    public String name() {
        return null;
    }*/
    //重写过滤器名字的方法，我们就用原名称就好。

    /**
     * 1.内部类 用来接收配置文件里的Test2=/toLogin.html,/login
     */
    @Data
    public static class Config{
        private List<String> paths;


    }

    /**
     * 4.该方法用来解析 /toLogin.html,/login 是什么的参数类型，是字符串？是集合？是数组？还是其他的？
     */
    @Override
    public ShortcutType shortcutType() {
        //return ShortcutType.DEFAULT;//将 /toLogin.html,/login  参数类型 字符串
        return ShortcutType.GATHER_LIST;//将 /toLogin.html,/login 参数类型 可变参数（数组）
    }


    /**
     * 5.确定 /toLogin.html,/login 的参数类型后，
     * 用"paths"接收参数，再转换成我们想要的参数类型,
     * 这个方法返回值会以某种方式，使得Config内部类的paths属性被赋值
     * config.getPaths()= ["/toLogin.html","/login"]
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("paths");//用"paths"接收参数，再转换成我们想要的参数类型List<>
    }
}
